import os
import uuid
import md5
import urlparse
import base64
import cgi
import re
import xml.dom
import xml.dom.minidom
import urllib

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import urlfetch, memcache
from google.appengine.ext.webapp import template
from google.appengine.ext import db

import models

SECURITY_KEY = 'security_key'

class IndexPage(webapp.RequestHandler):
	def __init__(self):
		self.indexhtml = os.path.join(os.path.dirname(__file__), 'index.html')

	def get(self):
		path = os.path.join(os.path.dirname(__file__), 'index.html')
		self.response.out.write(template.render(path, {}))

	def post(self):
		username = self.request.params['username']
		password = self.request.params['password']
		if not username or not password:
			content = template.render(self.indexhtml,
				{
				'error': 'username or password is empty',
				'username': username,
				'password': password
				})
			return self.response.out.write(content)
		query = models.Account.all().filter('username', username).filter('password', password)
		account = query.get()
		if not account:
			security_key = md5.new(uuid.uuid4().hex + SECURITY_KEY).hexdigest()
			account = models.Account(username=username, password=password, security_key=security_key)
			db.put(account)
		feed_url = urlparse.urljoin(self.request.url, '/FriendStatus/' + account.security_key + '.rss')
		content = template.render(self.indexhtml, {'feed_url': feed_url})
		self.response.out.write(content)

class FriendStatusPage(webapp.RequestHandler):
	def get(self, security_key):
		account = models.Account.all().filter('security_key', security_key).get()
		if not account:
			self.response.out.write('Wrong security key!')
			return self.error(404)
		auth = base64.standard_b64encode(account.username + ':' + account.password)
		result = urlfetch.fetch('http://api.twitter.com/1/statuses/home_timeline.atom', headers={'Authorization': 'Basic ' + auth})
		if result.status_code != 200:
			self.response.out.write('Wrong username or password!')
			return self.error(404)
		self.response.set_status(result.status_code)
		for k,v in result.headers.iteritems():
			self.response.headers[k] = v
		dom = xml.dom.minidom.parseString(result.content)
		self.filter_entry(dom)
		self.rewrite_url(dom)
		dom.writexml(self.response.out)

	def filter_entry(self, dom):
		filter_pattern = re.compile('^tweetmeme.+via @mashable', re.I)
		for entry_tag in dom.getElementsByTagName('entry'):
			title_tag = entry_tag.getElementsByTagName('title')[0]
			if title_tag and filter_pattern.match(title_tag.firstChild.nodeValue):
				entry_tag.parentNode.removeChild(entry_tag)

	url_pattern = re.compile('https?://\S+', re.I)

	def rewrite_url(self, dom):
		for content_tag in dom.getElementsByTagName('content'):
			urls = []
			for child in content_tag.childNodes:
				if child.nodeType == xml.dom.Node.TEXT_NODE:
					urls.extend(self.url_pattern.findall(child.nodeValue))
			url_list = ['<ul>']
			for url in urls:
				url_list.append('<li><a href="%s">Expand %s</a></li>' % (self.expand_url(url), url))
				url_list.append('<li><a href="https://liliangproxy.appspot.com/0/?url=%s">Proxy %s</a></li>' \
					% (urllib.quote(url), url))
			url_list.append('</ul>')
			content_tag.appendChild(dom.createTextNode(''.join(url_list)))

	def expand_url(self, url):
		expanded_url = memcache.get(url)
		if expanded_url:
			return expanded_url
		result = urlfetch.fetch(url, method=urlfetch.HEAD, follow_redirects=False)
		if result.status_code == 301 or result.status_code == 302:
			for k,v in result.headers.iteritems():
				if 'location' in k.lower():
					memcache.set(url, v)
					return v
		return url

	def rewrite_matched(self, text, pattern, callback):
		last_start = 0
		tokens = []
		for m in pattern.finditer(text):
			start,end = m.span(0)
			tokens.append(text[last_start:start] + callback(m))
			last_start = end
		tokens.append(text[last_start:])
		return ''.join(tokens)

application = webapp.WSGIApplication([
	 ('/', IndexPage), 
	 ('/FriendStatus/(?P<security_key>[0-9a-f]+).rss', FriendStatusPage), 
	],
	debug=True
	)

def main():
	run_wsgi_app(application)

if __name__ == "__main__":
	main()
